package cc.rengu.igas.share.core.service.channel.upgw;

import cc.rengu.igas.channel.upgw.facade.base.Header;
import cc.rengu.igas.channel.upgw.facade.bean.UpgwMchntInfo;
import cc.rengu.igas.channel.upgw.facade.request.UpgwEnterpriseGatewayFullPaymentRefundRequest;
import cc.rengu.igas.channel.upgw.facade.response.UpgwEnterpriseGatewayFullPaymentRefundResponse;
import cc.rengu.igas.channel.upgw.facade.result.Result;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.ShareServiceConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;

import java.util.*;

/**
 * UPGW 银联网关支付-企业网关支付退货
 * Created by lzl on 2021/4/23 11:08
 */
public class UpgwEnterpriseGatewayFullPaymentRefundService extends ChannelBaseService {
    @Override
    public Object callPreProc(TxnInfo txnInfo, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        Header upgwHeader = new Header();
        upgwHeader.setInstId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID));
        upgwHeader.setChanlId(channelCallCfg.getMsgSrcId());
        upgwHeader.setSrcSysId(AppParamConstant.SYS_ID);
        upgwHeader.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
        upgwHeader.setVersion(ShareParamConstant.DUBBO_VSERSION);
        upgwHeader.setTxnNum(channelCallCfg.getCallChannelTxn());
        upgwHeader.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        upgwHeader.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        upgwHeader.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        UpgwEnterpriseGatewayFullPaymentRefundRequest upgwEnterpriseRequest = new UpgwEnterpriseGatewayFullPaymentRefundRequest();
        ConvertUtil.convertOutput(upgwEnterpriseRequest);
        upgwEnterpriseRequest.setHeader(upgwHeader);

        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(upgwHeader.getInstId(), xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.MCHNT_NO));
        PayOrderInfo payOrderInfoUpgw = (PayOrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_PAY_ORDER_INFO);
        upgwEnterpriseRequest.setBusiType("100003");
        //交易金额
        upgwEnterpriseRequest.setOrderAmt(xmlTreeUtil.getXmlTreeStringValue("realRefundAmt"));
        //终端类型
        upgwEnterpriseRequest.setTermType(xmlTreeUtil.getXmlTreeStringValue("termType"));
        //原交易流水
        upgwEnterpriseRequest.setOrigTraceNo(Objects.requireNonNull(payOrderInfoUpgw).getChannelReconKey());
        //原交易时间
        upgwEnterpriseRequest.setOrigTransDate(payOrderInfoUpgw.getTxnDate());
        ///网关渠道标识
        upgwEnterpriseRequest.setPayeeIssrChannelId(payOrderInfoUpgw.getRemark1());
        //收款人账户信息
        upgwEnterpriseRequest.setPayeeAcctInfo(payOrderInfoUpgw.getPayeeAcctInfo());
        //收款人账户类型
        upgwEnterpriseRequest.setPayeeAcctType(convertAcctTypeToUpgwAcctType(payOrderInfoUpgw.getPayeeAcctType()));
        //报文初始发起机构标识 -银联机构号
        upgwEnterpriseRequest.setOriIssrId(mchntInfo.getCupsInstId());
        //商户信息
        UpgwMchntInfo upgwMchntInfo = new UpgwMchntInfo();
        upgwMchntInfo.setMchntNo(mchntInfo.getCupsMchntNo());
        upgwMchntInfo.setMchntType(mchntInfo.getIndustryType());
        upgwMchntInfo.setMchntName(xmlTreeUtil.getXmlTreeStringValue("mchntName"));
        upgwMchntInfo.setMchntTransSource(xmlTreeUtil.getXmlTreeStringValue("mchntTransSource"));
        upgwEnterpriseRequest.setMchntInfo(upgwMchntInfo);

        rglog.debug("UPGW 银联网关支付-企业网关支付退货请求:<{}>", JSON.toJSONString(upgwEnterpriseRequest));
        return upgwEnterpriseRequest;
    }

    @Override
    public PayOrderInfo generatePayOrderInfo(ChannelCallCfg channelCallCfg, OrderInfo orderInfo, Object request) throws Exception {
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        UpgwEnterpriseGatewayFullPaymentRefundRequest upgwEnterpriseRequest = (UpgwEnterpriseGatewayFullPaymentRefundRequest) request;
        BeanUtil.beanCopy(orderInfo.getUserOrderInfo(), payOrderInfo);
        if (orderInfo.getMchntOrderInfoList().size() == 1) {
            payOrderInfo.setMchntNo(orderInfo.getMchntOrderInfoList().get(0).getMchntNo());
        } else {
            payOrderInfo.setMchntNo(orderInfo.getUserOrderInfo().getGroupMchntNo());
        }
        payOrderInfo.setTxnNum(channelCallCfg.getTxnNum());
        payOrderInfo.setBizType(channelCallCfg.getBizType());
        payOrderInfo.setSysSeqNum(orderInfo.getUserOrderInfo().getSysSeqNum());
        payOrderInfo.setOrderCcy(orderInfo.getUserOrderInfo().getOrderCcy());
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
        payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
        payOrderInfo.setChannelSeqNum(Objects.requireNonNull(upgwEnterpriseRequest).getHeader().getTraceNo());
        payOrderInfo.setChannelReconKey(upgwEnterpriseRequest.getHeader().getTraceNo());
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setPayType(PayTypeEnum.OTHER_BANK_CARD.getPayType());
        payOrderInfo.setPayerAcctType(AcctTypeEnum.ALL.getAcctType());
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        payOrderInfo.setUserId(orderInfo.getUserOrderInfo().getUserId());
        return payOrderInfo;
    }

    @Override
    public Object callProc(ChannelCallCfg channelCallCfg, Object request) throws Exception {
        UpgwEnterpriseGatewayFullPaymentRefundRequest upgwEnterpriseRequest = (UpgwEnterpriseGatewayFullPaymentRefundRequest) request;
        /* Step1：调用接口，获取结果 */
        Result<UpgwEnterpriseGatewayFullPaymentRefundResponse> callResult;
        DubboService dubboService = new DubboServiceImpl();
        if (AppParamConstant.YES.equals(channelCallCfg.getSyncCallFlag())) {
            /* Step1.1：异步调用 */
            int iReturnCode;
            int callTimes = 0 == channelCallCfg.getSyncQueryRepeatNum() ? 1 : channelCallCfg.getSyncQueryRepeatNum();
            int gatTime = channelCallCfg.getSyncQueryRepeatTime();
            int gatType = StringUtil.isEmptyOrNull(channelCallCfg.getSyncQueryGapType()) ? 0 : Integer.parseInt(channelCallCfg.getSyncQueryGapType());
            if (ChannelCallModeEnum.LOCAL.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.1.1：异步应用内调用 */
                Class clasz = Class.forName(ShareServiceConstant.UPGW_PAY_SERVICE_INNER_PATH);
                iReturnCode = dubboService.asynCallDubboInnerMethod(clasz, ShareServiceConstant.UPGW_ENTERPRISE_GATEWAY_FULL_PAYMENT_REFUND_METHOD, upgwEnterpriseRequest, channelCallCfg.getSyncResultServiceName(), callTimes, gatType, gatTime);
            } else if (ChannelCallModeEnum.REMOTE.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.1.2：异步远程调用 */
                iReturnCode = dubboService.asynCallDubboService(ShareServiceConstant.UPGW_PAY_SERVICE, ShareServiceConstant.UPGW_ENTERPRISE_GATEWAY_FULL_PAYMENT_REFUND_METHOD, upgwEnterpriseRequest, channelCallCfg.getSyncResultServiceName(), callTimes, gatType, gatTime);
            } else {
                rglog.error("不支持的通道服务调用方式:{}，交易拒绝!", channelCallCfg.getChannelCallMode());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            }
            if (0 == iReturnCode) {
                return new BizResponse<>(OltpRpcdEnum.TRANS_SUCCESS.getRespCode(), OltpRpcdEnum.TRANS_SUCCESS.getRespDesc());
            } else {
                return new BizResponse<>(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            }
        } else {
            /* Step1.2：同步调用 */
            if (ChannelCallModeEnum.LOCAL.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.2.1：同步应用内调用 */
                Class clasz = Class.forName(ShareServiceConstant.UPGW_PAY_SERVICE_INNER_PATH);
                callResult = (Result<UpgwEnterpriseGatewayFullPaymentRefundResponse>) dubboService.callDubboInnerMethod(clasz, ShareServiceConstant.UPGW_ENTERPRISE_GATEWAY_FULL_PAYMENT_REFUND_METHOD, upgwEnterpriseRequest);
            } else if (ChannelCallModeEnum.REMOTE.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.2.2：同步远程调用 */
                callResult = (Result<UpgwEnterpriseGatewayFullPaymentRefundResponse>) dubboService.callDubboService(ShareServiceConstant.UPGW_PAY_SERVICE, ShareServiceConstant.UPGW_ENTERPRISE_GATEWAY_FULL_PAYMENT_REFUND_METHOD, upgwEnterpriseRequest);
            } else {
                rglog.error("不支持的通道服务调用方式:{}，交易拒绝!", channelCallCfg.getChannelCallMode());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            }
        }
        return callResult;
    }

    @Override
    public Object querySyncCallResult(PayOrderInfo payOrderInfo, Object request) {
        return null;
    }

    @Override
    public OrderInfo callResultOrderProc(OrderInfo orderInfo, String payOrderIndex, TransStatusEnum transStatusEnum, Object response) {
        OrderInfo updateOrderInfo = new OrderInfo();
        Result<UpgwEnterpriseGatewayFullPaymentRefundResponse> callResult = (Result<UpgwEnterpriseGatewayFullPaymentRefundResponse>) response;
        Optional<PayOrderInfo> payOrderInfoOpt = orderInfo.getPayOrderInfoList().stream().filter(item -> item.getDstCallIndex().equals(payOrderIndex)).findFirst();
        if (payOrderInfoOpt.isPresent() && null != callResult && null != callResult.getResult()) {
            UpgwEnterpriseGatewayFullPaymentRefundResponse enterpriseGatewayFullPaymentRefundResponse = callResult.getResult();
            PayOrderInfo payOrderInfo = payOrderInfoOpt.get();
            payOrderInfo.setTransStatus(transStatusEnum.getStatus());
            payOrderInfo.setRespCode(enterpriseGatewayFullPaymentRefundResponse.getRespCode());
            payOrderInfo.setRespDesc(enterpriseGatewayFullPaymentRefundResponse.getRespDesc());
            payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            switch (transStatusEnum) {
                case TRANS_SUCC:
                    payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
                    payOrderInfo.setSettleDate(DateUtil.getCurrentDate());
                    payOrderInfo.setChannelReconKey(payOrderInfo.getSysSeqNum());
                    orderInfo.getUserOrderInfo().setOrderStatus(OrderStatusEnum.FINISH.getStatus());
                    break;
                case TRANS_TIMEOUT:
                    payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
                    break;
                case SYSTEM_REJECT:
                    payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                    break;
                default:
                    break;
            }
            orderInfo.getUserOrderInfo().setTransStatus(payOrderInfo.getTransStatus());
            orderInfo.getUserOrderInfo().setBizStatus(payOrderInfo.getBizStatus());
            orderInfo.getMchntOrderInfoList().forEach(item -> {
                item.setTransStatus(payOrderInfo.getTransStatus());
                item.setBizStatus(payOrderInfo.getBizStatus());
            });
            updateOrderInfo.setUserOrderInfo(orderInfo.getUserOrderInfo());
            updateOrderInfo.setMchntOrderInfoList(orderInfo.getMchntOrderInfoList());
            updateOrderInfo.setPayOrderInfoList(Collections.singletonList(payOrderInfo));
        }
        return updateOrderInfo;
    }

    /**
     * 本系统账户类型转换为新网银的账户类型
     *
     * @param acctType 本系统账户类型
     * @return 新网银账户类型
     */
    private String convertAcctTypeToUpgwAcctType(String acctType) {
        rglog.trace("待转换的账户类型:<{}>", acctType);
        if (StringUtil.isEmptyOrNull(acctType)) {
            return acctType;
        }
        if ("00".equals(acctType) || "10".equals(acctType)) {
            return "01";
        } else if ("01".equals(acctType) || "11".equals(acctType)) {
            return "02";
        } else {
            rglog.info("新网银退款交易无法转换非借贷记的商户结算账户类型:<{}>", acctType);
            return acctType;
        }
    }
}
